﻿Imports System

''' <summary>
''' Provides extensions methods for <see cref="DateTime"/> object
''' </summary>
Public Module DateTimeExtensions
    Sub New()
    End Sub
    Private Const SQL_SERVER_MIN_YEAR As Integer = 1753
    Private Const USER_FORMAT As String = "{0} {1}"

    '''<summary>
    ''' Satisfies .net's Date with min date of MS SQL server (1st of January 1753 year)
    '''</summary>
    '''<param name="date">A date to satisfy</param>
    '''<returns>Satisfied date</returns>
    <System.Runtime.CompilerServices.Extension()> _
    Public Function SatisfyMSSqlMinDate(ByVal [date] As DateTime) As DateTime
        If [date].Year < SQL_SERVER_MIN_YEAR Then
            Return [date].AddYears(SQL_SERVER_MIN_YEAR - [date].Year)
        End If

        Return [date]
    End Function

    ''' <summary>
    ''' Calculates a date of the first day of a week <paramref name="date"/> 
    ''' belongs to
    ''' </summary>
    ''' <param name="date">Date to calculate first day from</param>
    ''' <returns>First day of a week of <paramref name="date"/></returns>
    <System.Runtime.CompilerServices.Extension()> _
    Public Function GetCurrentWeekStart(ByVal [date] As DateTime) As DateTime
        Dim currentDateStart = [date].[Date]
        Return currentDateStart.AddDays(1 - CInt(currentDateStart.DayOfWeek))
    End Function

    ''' <summary>
    ''' Calculates a date of the first day of a month <paramref name="date"/> 
    ''' belongs to
    ''' </summary>
    ''' <param name="date">Date to calculate first day from</param>
    ''' <returns>First day of a month of <paramref name="date"/></returns>
    <System.Runtime.CompilerServices.Extension()> _
    Public Function GetCurrentMonthStart(ByVal [date] As DateTime) As DateTime
        Dim currentDateStart = [date].[Date]
        Return currentDateStart.AddDays(1 - currentDateStart.Day)
    End Function

    ''' <summary>
    ''' Calculates a date of the first day of a year <paramref name="date"/> 
    ''' belongs to
    ''' </summary>
    ''' <param name="date">Date to calculate first day from</param>
    ''' <returns>First day of a year of <paramref name="date"/></returns>
    <System.Runtime.CompilerServices.Extension()> _
    Public Function GetCurrentYearStart(ByVal [date] As DateTime) As DateTime
        Dim currentMonthStart = [date].GetCurrentMonthStart()
        Return currentMonthStart.AddMonths(1 - currentMonthStart.Month)
    End Function

    ''' <summary>
    ''' Converts the value of the current System.DateTime object to its equivalent string representation using the specified format for particula User.  <paramref name="date"/> 
    ''' </summary>
    ''' <param name="date">A standard or custom date and time format string.</param>
    ''' <param name="forUser">A User the date convert for.</param>
    ''' <returns> standard or custom date and time format string.</returns>
    <System.Runtime.CompilerServices.Extension()> _
    Public Function ToStringFor(ByVal [date] As DateTime, ByVal forUser As IUserInfo) As String
        Dim userTimeZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(forUser.TimeZoneID)
        Dim userTime As DateTime = TimeZoneInfo.ConvertTime([date], userTimeZone)
        Return String.Format(USER_FORMAT, userTime.ToString("g"), forUser.TimeZoneAbbr)
    End Function

End Module

